package com.power.sifa.net.controller;

import com.alibaba.fastjson.JSON;
import com.aventrix.jnanoid.jnanoid.NanoIdUtils;
import com.plf.common.cache.CacheManager;
import com.plf.common.domain.PageDataResponse;
import com.plf.common.domain.ResponseDTO;
import com.plf.common.exception.BusinessException;
import com.plf.common.utils.SpringHolder;
import com.plf.common.utils.StringUtil;
import com.plf.core.base.service.Ha_entityormService;
import com.power.sifa.approve.model.enumeration.Per_card;
import com.power.sifa.net.api.lookupApi;
import com.power.sifa.net.model.Lookup;
import com.power.sifa.net.service.Lu_entityormService;
import io.swagger.annotations.Api;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.util.Assert;
import org.springframework.util.CollectionUtils;
import org.springframework.web.bind.annotation.RestController;

import javax.annotation.Resource;
import java.lang.reflect.Method;
import java.util.*;


@Slf4j
@RestController
@Api(value = "lookupExecutor", tags = {"表单回显"})
public class LookupController implements lookupApi {

    @Autowired
    private CacheManager cacheManager;

    @Resource
    private Lu_entityormService lu_entityormService;

    @Resource
    private Ha_entityormService ha_entityormService;

//    @Resource
//    private Apl_per_commonService apl_per_commonService;

    @Override
    public ResponseDTO lookupOne(Lookup lookup) throws Exception {
        Assert.notNull(lookup.getTable(), lookup.getTable() + "未配置数据查询服务");

        Class table_clazz = findClassByTable(lookup.getTable());
        List list = lu_entityormService.findList(table_clazz, lookup.getParams(), lookup.getPageInfo());
        if (!CollectionUtils.isEmpty(list)) {
            // 2. 配置企业表和申请表的映射关系
            Map<String, Object> result = JSON.parseObject(JSON.toJSONString(list.get(0)), Map.class);
            Map<String, Object> aplFormObj = new HashMap<>(16);
            for (Map.Entry<String, String> entry : lookup.getMaprelation().entrySet()) {
                if (result.get(entry.getKey()) != null) {
                    aplFormObj.put(entry.getValue(), result.get(entry.getKey()));
                }
            }
            return ResponseDTO.succData(aplFormObj);
        }
        return ResponseDTO.succData(null);
    }

    @Override
    public ResponseDTO lookupList(Lookup lookup) throws Exception {
        Assert.notNull(lookup.getTable(), "未配置数据查询服务");

        Class table_clazz = findClassByTable(lookup.getTable());
        List list = lu_entityormService.findList(table_clazz, lookup.getParams(), lookup.getPageInfo());
        PageDataResponse page = new PageDataResponse();
        if (!CollectionUtils.isEmpty(list)) {
            // 如果包含sortnum字段, 则根据该字段排序
            list = JSON.parseArray(JSON.toJSONString(list), Map.class);
            if (null != ((Map) list.get(0)).get("sortnum")) {
                Collections.sort(list, (o1, o2) -> (int) ((Map) o1).get("sortnum") > (int) ((Map) o2).get("sortnum") ? 1 : -1);
            }
            Long total = Long.valueOf(lookup.getPageInfo().getAllcount());
            int size = lookup.getPageInfo().getPageSize() * lookup.getPageInfo().getPageNumber();
            if (total.intValue() - size > 0) {
                Integer num = lookup.getPageInfo().getPageNumber() + 1;
                page.setNextPage(num);
            }
            page.setSize(lookup.getPageInfo().getPageSize());
            page.setCurrent(lookup.getPageInfo().getPageNumber());
            page.setTotal(total);
            page.setRecords(list);
        } else {
            page.setSize(0);
            page.setCurrent(1);
            page.setTotal(0L);
            page.setRecords(list);
        }
        return ResponseDTO.succData(page);
    }

    @Override
    public ResponseDTO lookupAplInit(String applyid, Lookup lookup) throws Exception {
        Assert.notNull(lookup.getTable(), "未配置数据查询服务");
        Assert.notNull(lookup.getApltable(), "未传入数据保存申请表");
        Assert.notNull(lookup.getMaprelation(), "未传入两表映射关系");

        Class table_clazz = findClassByTable(lookup.getTable());
        // 1. 先查申请表有没有数据, 有数据往申请表存储一份
        List<Object> entList = lu_entityormService.findList(table_clazz, lookup.getParams(), lookup.getPageInfo());
        List<Map> list = JSON.parseArray(JSON.toJSONString(entList), Map.class);
        if (!CollectionUtils.isEmpty(list)) {
            List<Map> aplList = new ArrayList<>(10);
            for (Map<String, Object> result : list) {
                Map<String, Object> aplFormObj = new HashMap<>(16);
                // 2. 配置企业表和申请表的映射关系
                for (Map.Entry<String, String> entry : lookup.getMaprelation().entrySet()) {
                    if (result.get(entry.getKey()) != null) {
                        aplFormObj.put(entry.getValue(), result.get(entry.getKey()));
                    }
                }
                // 2.1 回显srcid
                if (result.get("id") != null) {
                    aplFormObj.put("srcid", Integer.valueOf(result.get("id").toString()));
                }
                // 2.2 多个是从表靠applyid关联, 单个是继承主表靠id = applyid关联
                if (lookup.getIsMainTable()) {
                    aplFormObj.put("id", applyid);
                } else {
                    aplFormObj.put("id", applyid + NanoIdUtils.randomNanoId());
                    aplFormObj.put("applyid", applyid);
                }
                aplList.add(aplFormObj);

            }
            // 如果是继承主表在apl表初始化一个, 如果是从表则初始化所有
            if (lookup.getIsMainTable()) {
                // 存储申请表数据 (继承主表) (主表永远不初始化)
                if ("apl_main".equals(lookup.getApltable()) == false) {
                    this.ha_entityormService.saveObject(this.findClassByTable(lookup.getApltable()), "id", aplList.get(0));
                }
                return ResponseDTO.succData(aplList.get(0));
            } else {
                // 存储申请表数据 (从表)
                for (Map v : aplList) {
                    this.ha_entityormService.saveObject(this.findClassByTable(lookup.getApltable()), "id", v);
                }
                return ResponseDTO.succData(aplList);
            }

        }
        return ResponseDTO.succData(null);
    }

    @Override
    public ResponseDTO lookupAplBatchInit(String applyid, List<Lookup> lookupList) throws Exception {
        Map<String, Object> result = new HashMap<>(16);
        for (Lookup v : lookupList) {
            ResponseDTO res = this.lookupAplInit(applyid, v);
            if (res.getCode() != 0) {
                log.error("批量数据初始化企业库数据失败 -> msg[{}]", res.getMsg());
                return ResponseDTO.wrap(500, res.getMsg());
            }
            result.put(v.getApltable(), res.getData());
        }
        return ResponseDTO.succData(result);
    }

    @Override
    public ResponseDTO lookupAplByid(String applyid, String apltable) throws Exception {
        Assert.notNull(applyid, "未传入申请表id");
        Assert.notNull(apltable, "未传入申请表");

        return ResponseDTO.succData(ha_entityormService.findOne(this.findClassByTable(apltable), "id", applyid));
    }

    @Override
    public ResponseDTO lookupSaveApl(String apltable, Map<String, Object> body) throws Exception {
        Assert.notNull(apltable, "未传入申请表名称");
        String id = (String) body.get("id");
        Map<String, Object> result = new HashMap<String, Object>(16);

        if (StringUtil.isEmpty(id)) {
            return ResponseDTO.wrap(500, "id不能为空! /executor/lookupSaveApl");
        }
        // 如果是人的类型, 校验身份证信息
        if (null != body.get("cardtype") && Per_card.IDCARD == Integer.valueOf(body.get("cardtype").toString())) {
            String name = (String) body.get("name");
            String cardno = (String) body.get("cardno");
            if (StringUtil.isEmpty(name)) {
                result.put("code", -1);
                result.put("msg", "人员姓名为空");
                return ResponseDTO.succData(result);

            }
            if (StringUtil.isEmpty(cardno)) {
                result.put("code", -1);
                result.put("msg", "人员证件号为空");
                return ResponseDTO.succData(result);
            }
            // 身份证信息两项比对
//            Boolean check = this.apl_per_commonService.check2(name, cardno);
//            if(check == false) {
//                result.put("code", -1);
//                result.put("msg", "证件号与身份信息不匹配");
//                return ResponseDTO.succData(result);
//            }
        }

        this.ha_entityormService.saveObject(this.findClassByTable(apltable), "id", body);

        // 调一下同步补正接口(通用)
//        Apl_attach_append_listService apl_attach_append_listService = SpringHolder.getBean(Apl_attach_append_listService.class);
//        apl_attach_append_listService.syncAppend(id, apltable,  id);

        result.put("code", 0);
        result.put("msg", "保存成功");
        return ResponseDTO.succData(result);
    }

    @Override
    public ResponseDTO lookupBatchSaveApl(String apltable, List<Map<String, Object>> body) throws Exception {
        Assert.notNull(apltable, "未传入申请表名称");

        Class cls = SpringHolder.getBean(apltable).getClass();
        List saveList = JSON.parseArray(JSON.toJSONString(body), cls);

        Object objService = SpringHolder.getBean(apltable + "ServiceImpl");
        Method method = objService.getClass().getDeclaredMethod("saveAll", List.class);
        method.invoke(objService, saveList);

        // 调一下同步补正接口(通用)
        // Apl_attach_append_listService apl_attach_append_listService = SpringHolder.getBean(Apl_attach_append_listService.class);
        for (Map<String, Object> v : body) {
            if (v.get("id") != null && v.get("applyid") != null) {
                // apl_attach_append_listService.syncAppend((String) v.get("applyid"), apltable, (String) v.get("id"));
            }
        }

        return ResponseDTO.succ();
    }

    /**
     * 通过表名, 从缓存中找到model类的全名
     * 缓存在TableMapRunner中初始化
     *
     * @param table: 表名, 忽略大小写, 缓存都转成小写
     * @return class对象
     * @throws Exception
     */
    private Class findClassByTable(String table) throws Exception {
        String classname = (String) cacheManager.get("TABLE-ENTITY", table);
        if (classname == null) {
            throw new BusinessException("无法获取表对应的实体对象: " + table);
        }

        Class clazz = Class.forName(classname);
        return clazz;
    }
}
